package cn.zl.api.impl.login;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.yunbamboos.Const;
import cn.yunbamboos.exception.AppException;
import cn.yunbamboos.rest.service.anno.RestServiceDTO;
import cn.yunbamboos.rest.service.anno.RestServiceMapping;
import cn.yunbamboos.rest.service.dto.out.BaseOutDTO;
import cn.yunbamboos.token.IToken;
import cn.yunbamboos.token.TokenBuilder;
import cn.yunbamboos.token.event.LoginTokenEvent;
import cn.yunbamboos.token.event.LogoutTokenEvent;
import cn.yunbamboos.utils.UserPasswordUtils;
import cn.zl.api.dto.login.LoginInDTO;
import cn.zl.api.dto.login.LoginOutDTO;
import cn.zl.api.dto.login.LogoutInDTO;
import cn.zl.api.dto.login.LogoutOutDTO;
import cn.zl.api.inter.login.ILoginService;
import cn.zl.mapper.UserMapper;
import cn.zl.model.User;

import jakarta.annotation.Resource;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;

@Service("LoginServiceImpl")
public class LoginServiceImpl implements ILoginService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @RestServiceMapping(url = "/web/login/login", name = "web界面登陆服务", authentication = false)
    @RestServiceDTO(in = LoginInDTO.class, out = LoginOutDTO.class)
    @Override
    public BaseOutDTO login(LoginInDTO in) {
        LoginOutDTO out = new LoginOutDTO();
        // 登录账号
        String loginName = in.getLoginName();
        // 登录密码
        String password = UserPasswordUtils.encrypt(in.getPassword());
        // 登录IP
        String ip = in.getSession("client_ip");
        // 登录浏览器
        String browser = in.getSession("browser");
        // 登录时间
        String loginTime = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN);

        Optional<User> optional = userMapper.queryByLoginName(loginName);
        if (optional.isEmpty()) {
            throw AppException.c("账号或者密码错误");
        }
        User user = optional.get();
        // 验证用户密码
        if (!user.getPassword().equals(password)) {
            throw AppException.c("账号或者密码错误");
        }
        String userId = user.getUserId();
        // 生成token
        IToken token = new TokenBuilder().id(UUID.randomUUID().toString())
                .ip(ip)
                .browser(browser)
                .set("user_id", userId)
                .set("login_time", loginTime)
                .secret(Const.TOKEN_SECRET)
                .issuer(Const.TOKEN_ISSUER)
                .createTime(System.currentTimeMillis())
                .expireTime(Const.TOKEN_EXPIRE_TIME * 1000L).build();
        String id = token.toID();
        // 登陆token事件
        LoginTokenEvent event = new LoginTokenEvent(this);
        event.setId(id);
        event.setToken(token.create());
        this.applicationEventPublisher.publishEvent(event);
        // 记录日志 用户ID
        // OperateLogThreadLocal.setUserId(userId);
        out.setToken(id);
        return out;
    }

    @RestServiceMapping(url = "/web/login/logout", name = "web界面注销服务")
    @RestServiceDTO(in = LogoutInDTO.class, out = LogoutOutDTO.class)
    @Override
    public BaseOutDTO logout(LogoutInDTO in) {
        // 退出登陆token事件
        LogoutTokenEvent event = new LogoutTokenEvent(this);
        event.setId(in.getHeader("token"));
        this.applicationEventPublisher.publishEvent(event);
        return new LogoutOutDTO();
    }

}
